Skip to content

pull in latest upstream - #2

Open
TtheBC01 wants to merge 843 commits into
1Shot-API:mainfrom
x402-foundation:main
Open

pull in latest upstream#2
TtheBC01 wants to merge 843 commits into
1Shot-API:mainfrom
x402-foundation:main

Conversation

@TtheBC01

Copy link
Copy Markdown

Description

Tests

Checklist

  • I have formatted and linted my code
  • All new and existing tests pass
  • My commits are signed (required for merge) -- you may need to rebase if you initially pushed unsigned commits
  • I added a changelog fragment for user-facing changes (docs-only changes can skip)

phdargen and others added 18 commits May 15, 2026 20:01
* bump next

* changeset

* fix format

* fix lint

* fix paywall
* Update docs/extensions/sign-in-with-x.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

* Update docs/extensions/sign-in-with-x.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

* Update docs/extensions/sign-in-with-x.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

* Update docs/extensions/sign-in-with-x.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

---------

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
* Update docs/advanced-concepts/lifecycle-hooks.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

* Update docs/sdk-features.md

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

---------

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
* add checks for 0 settle/refund amounts

* same for go
* specs: add NEAR v2 exact payment scheme spec

* address PR1 comment about height vs time for timeout, how we had payer being returned oddly

* update PaymentRequirements removing extra field, adding max timeout, clarity on when settlement happens

* add clarity about yoctoNEAR deposit and access key verification, and how it applies with delegate actions

and proactively added Duplicate Settlement Mitigation section

* clarify the attached deposit in metatxs for both native transfer and ft_transfer/ft_transfer_call

* improve "Token Transfer Intent and Exactness" about what's prepaid by client and relayer

* add section "Implementing Verification with NEAR RPC"

* wrap up details on facilitator sponsorship, vulnerability and mitigation sections
…dev framing (#2160)

Address forensic review-quorum findings and conform SVM paywall to upstream pattern:

- Drop dead solana:TESTNET FAUCET_URLS entry (Circle faucet does not
  dispense USDC on Solana Testnet; Option B renders "No faucet configured."
  for any unmapped chain).
- Revert all Solana Testnet recognition added by prior refactor pass
  (SOLANA_NETWORK_REFS.TESTNET constant, getNetworkDisplayName branch,
  isTestnetNetwork OR-branch). The paywall now recognizes one non-mainnet
  SVM network — Devnet — matching upstream/main. No SVM dev expects
  paywall Testnet support; upstream doesn't provide it.
- Unify "Need {tokenName} on {chainName}?" copy in SolanaPaywall and
  AvmPaywall payment-required headers (were hardcoded "USDC"; matches
  EvmPaywall).

Closes #2159
The custom client example referenced process.env.SERVER_URL (undefined in
.env-local) and hardcoded /weather, silently falling back to the localhost
default. Align with the canonical pattern used by the fetch and axios
client examples.
Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
The MCP payment wrappers in server_sync.py and server_async.py called
facilitator.settle() but never branched on settle_result.success before
returning the wrapped tool's output. A signed EIP-3009 authorization
could be replayed indefinitely: verify passed each time, the tool ran,
settle returned success=False with AuthorizationAlreadyUsed, and the
wrapper returned the tool output stamped with the failed settlement
response in _meta.

Mirror the success check from the non-MCP path in server.py and route
to the existing _create_settlement_failed_result_{sync,async} helpers
on failure. Add regression tests covering the success=False branch
(distinct from the existing exception-path test) and assert that
on_after_settlement does not fire on failure.

Also fix a stale signature on the test mock's
_create_payment_required_response_real that was missing the extensions
parameter, which had been masking other test failures.
…2352)

* add ERC-6492 unwrapping

* same for py/go

* add changeset

* fix tvm e2e config
* fix smart wallet signatures and filestorage bundling

* same for redis

* changeset
* Update docs/schemes/batch-settlement.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

* Update docs/schemes/batch-settlement.mdx

Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

---------

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
* add skip and skipHandler return primitives to resource server hooks

* add onVerifiedPaymentCanceled/cancelDispatcher/onProtectedRequest hooks

* add client hooks onPaymentResponse and onPaymentRequired

* add extension 402/settlement enrichment hooks and policy

* wire scheme and extension lifecycle hook adapters

* add changelog
Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
Align the auth-capture scheme name with the new spec folder and file naming.

Co-authored-by: Cursor <cursoragent@cursor.com>
phdargen and others added 30 commits July 24, 2026 17:44
* add facilitator faq

* minor fixes
)

HTTPFacilitatorClient's `createAuthHeaders` callback must return an object
keyed by facilitator path (`verify`/`settle`/`supported`). Returning a flat
headers object silently indexed to `undefined` and dropped auth on every
request, surfacing as an unexplained 401. Throw a clear error on the wrong
shape and document the expected shape.

Fixes #2762
…it rejection (#2974)

* fix: add request timeouts to HTTPFacilitatorClient and guard eager init rejection

verify(), settle(), and getSupported() previously called fetch() with no
deadline, so a facilitator that accepted a connection but never completed
the response hung the operation indefinitely — and, through the eagerly
created initPromise shared by the Hono/Express/Fastify/Next middlewares,
wedged every protected route until restart.

- Add FacilitatorConfig.timeoutMs (default 30s, matching the Go and
  Python facilitator clients), applied via a fresh AbortSignal.timeout()
  per HTTP attempt, covering response headers and body consumption.
- Reject with a typed FacilitatorTimeoutError (a FacilitatorResponseError
  subclass the middlewares already surface as 502) instead of a raw
  DOMException; settle() timeouts are documented as indeterminate.
- Attach a rejection handler to the eager initPromise in all four
  middlewares so an early init failure cannot become an unhandled
  rejection; the first protected request still observes it and retries.

Closes #2961

* fix: surface deadline aborts from error-body reads and validate timer-safe timeoutMs

Review follow-ups on #2974:

- getSupported() swallowed a deadline abort raised while reading a non-2xx
  error body, reporting it as a generic HTTP failure — which middleware
  surfaces as a 500 instead of the typed 502, and which the 429 path would
  even retry after the deadline had fired. Abort/timeout rejections from
  response.text() are now rethrown so the FacilitatorTimeoutError
  conversion applies; statusText remains the fallback for other body-read
  failures.
- timeoutMs now requires a positive safe integer of at most 2^31 - 1:
  AbortSignal.timeout() throws ERR_OUT_OF_RANGE on non-integers at request
  time, and larger values overflow Node's 32-bit timers into an effective
  ~1ms deadline while reporting the configured duration.
* fix enrichPaymentPayload

* same for go

* same for py
* fix(go/http): add Cache-Control: no-store to 402 responses

* add cache-control policy for payment HTTP responses

---------

Co-authored-by: Philippe d'Argent <pdargent@icloud.com>
* fix(ts/py): add cache control, no-store for 402, private for 200

* add changeset
Three inaccuracies that mislead anyone following the add-a-default-asset
runbook verbatim.

1. The Python snippet used NetworkConfig(...)/AssetInfo(...) constructor
   syntax with AssetTransferMethod.PERMIT2. AssetTransferMethod does not
   exist anywhere in the Python package, so uncommenting that line raises
   NameError; the real value is the literal string "permit2". Every one of
   the ~30 entries in NETWORK_CONFIGS is a plain dict literal with
   snake_case string keys. Rewritten to match.

2. The Go snippet used ChainID: big.NewInt(YOUR_CHAIN_ID) while every real
   entry uses a named constant from the ChainID* var block, so the doc
   silently omitted a required step. Now shows the constant declaration.

3. Six comments referenced DEFAULT_ASSET.md; the file is DEFAULT_ASSETS.md.
   The TypeScript one also placed it in a nonexistent exact/server/
   directory; it lives at the repository root.

Comment- and markdown-only: no behaviour change, so no changelog fragments
per CONTRIBUTING.md.

Co-authored-by: Claude <noreply@anthropic.com>
…lt stablecoin (#3025)

Celo had no entry in the default-asset registries, so a resource server on
Celo could not write price: "$0.01" — dollar-string pricing resolves through
the per-chain default-stablecoin map and had to fall back to an explicit
TokenAmount with amountInAtomicUnits.

Registry-only change: no new logic, no new files outside changelog fragments.
Network stays an open-ended CAIP-2 string and EVM schemes register on the
wildcard eip155:*, so nothing gated Celo other than the missing map entries.

Default asset (verified on-chain via forno.celo.org and
forno.celo-sepolia.celo-testnet.org):

  Celo Mainnet  eip155:42220     USDC 0xcebA9300f2b948710d2653dD7B07f33A8B32118C
  Celo Sepolia  eip155:11142220  USDC 0x01C5C0122039549AD1493B8220cABEdD739BC44E

Both: EIP-712 domain name "USDC", version "2", 6 decimals, EIP-3009
transferWithAuthorization present (authorizationState returns cleanly). Each
domain separator was recomputed from the committed name/version/chainId/address
and byte-matched against the contract's own DOMAIN_SEPARATOR():

  42220     0xb2ce31d2838445fa765a491f550e7c78ac7280ab0f3bc9d6063a86df9c3fb578
  11142220  0x23f491197bb8c5ea4fe8dd4c2293b600f073553f9814015e7a5eb57724df9578

Asset selection rationale (DEFAULT_ASSETS.md section 4):

- USDC over USDT. Both are EIP-3009-capable 6-decimal tokens on Celo, but
  USDT's version() reverts on-chain, so its EIP-712 version cannot be read the
  way this table's contract assumes. USDT (0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e)
  remains fully usable via an explicit TokenAmount.
- cUSD / USDm (0x765DE816845861e75A25fCA122bb6898B8B1282a) is not viable: Mento
  StableTokenV2, 18 decimals, EIP-2612 only, authorizationState reverts. It
  would force the Permit2 path.
- Alfajores is excluded — its RPC is unreachable and Circle no longer lists a
  USDC there. Celo Sepolia is the live testnet.

Also adds the v1 legacy network name "celo" so that getEvmChainIdV1("celo")
resolves to 42220 instead of throwing. The production Celo facilitator
advertises {"x402Version": 1, "scheme": "exact", "network": "celo"} in its
/supported response, which no SDK could previously resolve. Mainnet only; the
v1 name space has no Celo testnet name.

Decimals are 6 on both networks, so evm/gen/decimals.ts needs no regeneration.

Co-authored-by: Claude <noreply@anthropic.com>
Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
Returning a response after payment reconciliation fails is misleading, while dropping it without closing its body leaks resources.
* don't clobber client builder codes

* address review

* fixes

* scope only to builder codes

* caps on both sides

* fix go lint
Registers Flare mainnet (eip155:14) with USD0 as the default stablecoin across the TypeScript, Go and Python SDKs, plus the v1 legacy network maps and the support-table docs. Follows DEFAULT_ASSETS.md; no paywall regeneration needed (6 decimals).

EIP-712 domain parameters were verified by RECOMPUTATION rather than read and trusted: hashDomain({name, version: "1", chainId: 14, verifyingContract}) computed from the values as written in each of the three SDK files equals the token's on-chain DOMAIN_SEPARATOR 0x4c53d754dcb2f406ecf83695856d8c10b13296a318d9a481043412bf253d43ae.

EIP-3009 support confirmed on-chain: transferWithAuthorization with a junk signature reverts "TetherToken: invalid signature" (the function exists and validates), and authorizationState(address,bytes32) returns cleanly.
…3033)

The recovery retry previously created a fresh payment payload from a
server-controlled PaymentRequired without re-running abort/approval
hooks, so a corrective 402 could escalate amount/asset/payTo unnoticed.
* fix: match dotAll for line terminators in wildcard regex route

* chore: add changeset versions

* fix: format

* fix: format/lint

* fix: clean up narrative comments
* fix(python): verify Transfer event after exact/eip3009 settle

Parity with Go #2727 and open TS #2385: do not treat receipt.status alone
as proof the expected ERC-20 Transfer occurred.

* style(python): ruff format eip3009 transfer-event verify

Address maintainer review on #3032 (lint-python / formatting).

* style(python): address review on transfer-event settle comments

Shorten facilitator comment; drop TransactionReceipt field commentary
per maintainer feedback on #3032.
…3034)

* fix(mcp): plumb spend policies through createx402MCPClient factory

The documented factory previously built a bare x402Client and dropped
policies/selector. Route through fromConfig so integrators can bound spend.

* docs(mcp): drop old-implementation comments in factory helper

Document current fromConfig/policies behaviour only, per #3034 review.
Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
…#2385)

* fix(evm): verify Transfer event in receipt after exact/eip3009 settle

settleEIP3009 currently treats receipt.status === "success" as proof of a
successful transfer. The receipt's status only tells us the tx did not revert;
it does not tell us that the expected ERC-20 Transfer was emitted from the
expected token contract with the expected (from, to, value).

The EVM batch-settlement facilitator and the Stellar exact facilitator already
perform this kind of receipt-shape check (parseEventLogs over receipt.logs,
filtered by token address, matched against the expected event arguments). This
PR brings exact/eip3009 in line with that pattern.

Behavior: a tx whose status is success but whose receipt logs do not contain a
matching ERC-20 Transfer is now reported as a settlement failure with the new
ErrTransferEventMismatch error code (wire string
invalid_exact_evm_transfer_event_mismatch) instead of being reported as a
successful settle. The happy path is unchanged.

* address review and align Transfer check with go/py

---------

Co-authored-by: Philippe d'Argent <pdargent@icloud.com>
* fix: reject external / in bazaar discovery schema (SSRF)

* chore: clean up spec wording

* fix: format/lint
Generated-By: mintlify-agent

Mintlify-Source: dashboard-editor

Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.